#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
# author: 小菠萝测试笔记
# blog:  https://www.cnblogs.com/poloyy/
# time: 2021/10/13 10:00 上午
# file: crud_user.py
"""
from typing import Any, Dict, List, Optional, Union

from fastapi.encoders import jsonable_encoder
from sqlalchemy.orm import Session

from app.core.security import get_password_hash, verify_password
from app.crud.base import CRUDBase
from app.models import User
from app.schemas.user import UserCreate, UserUpdate


class CRUDUser(CRUDBase[User, UserCreate, UserUpdate]):
    def create(self, db: Session, *, user_create: UserCreate) -> User:
        """
        创建 user 需要加密 password
        :param db: 数据库对象
        :param user_create: UserCreate Model
        :return: User ORM Model
        """
        user_data = jsonable_encoder(user_create)
        user_data["password"] = get_password_hash(user_data["password"])
        return super(CRUDUser, self).create(db, obj_in=user_data)

    def update(
        self, db: Session, *, db_obj: User, obj_in: Union[UserUpdate, Dict[str, Any]]
    ) -> User:
        """
        更新 user 需要加密 password
        :param db: 数据库对象
        :param db_obj: User
        :param obj_in: UserUpdate or Dict
        :return: User ORM Model
        """
        if isinstance(obj_in, dict):
            update_data = obj_in
        else:
            update_data = obj_in.dict(exclude_unset=True)
        if update_data.get("password"):
            update_data["password"] = get_password_hash(update_data["password"])
        return super(CRUDUser, self).update(db, db_obj=db_obj, obj_in=update_data)

    def authenticate(
        self, db: Session, *, username: str, password: str
    ) -> Optional[User]:
        """
        校验用户名、密码
        :param db: 数据库对象
        :param username: 用户名
        :param password: 密码
        :return: None or User
        """
        db_obj = self.get_by_username(db, username=username)
        if not db_obj:
            return None
        if not verify_password(password, db_obj.password):
            return None
        return db_obj

    def active_user(self, db: Session, *, id: int, state: int = 1) -> Optional[User]:
        """
        修改用户状态
        :param db: 数据库对象
        :param id: 用户id
        :param state: 状态
        :return: None or User
        """
        db_obj = self.get(db, id=id)
        if not db_obj:
            return None
        setattr(db_obj, "state", state)
        db.add(db_obj)
        db.commit()
        db.refresh(db_obj)
        return db_obj

    @staticmethod
    def get_by_username(db: Session, *, username: str) -> Optional[User]:
        """
        根据 username 获取用户
        :param db: 数据库对象
        :param username: 用户名
        :return: None or User ORM Model
        """
        return db.query(User).filter(User.username == username).first()

    @staticmethod
    def get_by_email(db: Session, *, email: str) -> Optional[User]:
        """
        根据 email 获取用户
        :param db: 数据库对象
        :param email: email
        :return: None or User ORM Model
        """
        return db.query(User).filter(User.email == email).first()

    @staticmethod
    def get_by_phone(db: Session, *, phone: str) -> Optional[User]:
        """
        根据 phone 获取用户
        :param db: 数据库对象
        :param phone: phone
        :return: None or User ORM Model
        """
        return db.query(User).filter(User.phone == phone).first()

    @staticmethod
    def get_total_user(
        db: Session, *, username: Optional[str] = None, name: Optional[str] = None
    ) -> int:
        """
        获取用户数
        :param db: 数据库对象
        :param username: 用户名
        :param name: 用户名字
        :return: int
        """
        count = 0
        if not username and not name:
            count = db.query(User).count()
        elif name and not username:
            count = db.query(User).filter(User.name == name).count()
        elif username and not name:
            count = db.query(User).filter(User.username == username).count()
        elif username and not name:
            count = (
                db.query(User)
                .filter(User.username == username, User.name == name)
                .count()
            )
        return count

    @staticmethod
    def get_by_state(db: Session, *, state: int = 1) -> Optional[List[User]]:
        """
        根据状态返回
        :param db:
        :param state:
        :return:
        """
        return db.query(User).filter(User.state == state, User.is_delete != 1).all()


user = CRUDUser(User)
